package com.zhitan.ems.app.stat.controller;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.influxdb.query.FluxTable;
import com.zhitan.ems.app.iot.entity.DeviceEntity;
import com.zhitan.ems.app.iot.entity.DevicePropertyEntity;
import com.zhitan.ems.app.iot.entity.DevicePropertyGroupEntity;
import com.zhitan.ems.app.iot.enums.ENERGY_TYPES_ENUM;
import com.zhitan.ems.app.iot.service.DevicePropertyGroupService;
import com.zhitan.ems.app.iot.service.DevicePropertyService;
import com.zhitan.ems.app.iot.service.DeviceService;
import com.zhitan.ems.app.stat.service.impl.InfluxdbService;
import com.zhitan.ems.app.stat.vo.DeviceDataDateVo;
import com.zhitan.ems.common.core.controller.BaseController;
import com.zhitan.ems.common.core.domain.R;
import com.zhitan.ems.common.extra.utils.MapUtils;
import com.zhitan.ems.common.extra.utils.StringUtil;
import com.zhitan.ems.framework.core.vo.VPage;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;

/**
 * 统计数据表
 * @author zhitan
 * @date 2025-09-19 22:59:37
 */
@Api(tags = "实时统计", value = "实时统计")
@RestController
@RequestMapping("intra/stat/realtime")
public class StatisticsRealTimeController extends BaseController{
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private InfluxdbService influxdbService;
    @Value("${influx.bucket}")
    private String bucket;
    @Autowired
    private DevicePropertyGroupService devicePropertyGroupService;
    @Autowired
    private DevicePropertyService devicePropertyService;
    @ApiOperation(value = "设备实时数据from 时序库", response = Map.class)
    @GetMapping("device")
    @PreAuthorize("@ss.hasPermi('stat:statisticsday:list')")
    public R<Map<String, Object>> device(@RequestParam("deviceId") Long deviceId ) throws ParseException {
        Map<String, Object> result = new HashMap<>();
        DeviceEntity device=deviceService.getById(deviceId);
        result.put("device", device);
        if(device==null) {
        	return R.error("设备不存在！");
        }
        List<DevicePropertyGroupEntity> groupDataList=null;
        if(device.getEnergyType()!=null) {
        	groupDataList=devicePropertyGroupService.getByEnergyType(device.getEnergyType());
        }
        List<DevicePropertyEntity> proPertyList=null;
        if(device.getDeviceTypeId()!=null&&device.getDeviceTypeId()>0) {
       	    proPertyList=devicePropertyService.getByTypeId(device.getDeviceTypeId(), 1);
            result.put("proPertyList", proPertyList);
        }
        if(device.getIsVirtual()!=null&&device.getIsVirtual()==1) {
        	  return R.ok(result);
        }
        ENERGY_TYPES_ENUM energyType= ENERGY_TYPES_ENUM.findByCode(device.getEnergyType());
        String table ="emsplus";//energyType.getTable();
		String start ="-1d";
		List<FluxTable> fluxTableList = influxdbService.getLastInfluxDataByDeviceCode(bucket, start, null, table, device.getDeviceCode());
    	DeviceDataDateVo dataDateVo = InfluxdbService.getResultOneRowByTagProcess(fluxTableList,true);
    	if(dataDateVo==null||dataDateVo.getData()==null) {
    		return R.error("无数据");
    	}
		Map<String, Object> fluxData=dataDateVo.getData();
		if(groupDataList!=null&&proPertyList!=null&&proPertyList.size()>0) {
			List<DevicePropertyEntity> otherPertyDataList=new ArrayList<DevicePropertyEntity>();
			for(DevicePropertyEntity item:proPertyList) {
             	if(item.getDataFormCode()!=null&&fluxData.containsKey(item.getDataFormCode())) {
             		item.setDataFormCodeValue(fluxData.get(item.getDataFormCode()));
             	}
             	item.setDataFormTime(dataDateVo.getDate());
             	boolean otherFlag=false;
             	for(DevicePropertyGroupEntity group:groupDataList) {
	  				  List<DevicePropertyEntity> proPertyDataList=group.getProPertyList();
	  				  if(proPertyDataList==null) {
	  					  proPertyDataList=new ArrayList<DevicePropertyEntity>();
	  				  }
	  				  if(item.getGroupCode()!=null&&group.getGroupCode()!=null&&item.getGroupCode().equalsIgnoreCase(group.getGroupCode())) {
	             		  proPertyDataList.add(item); 
	             		  otherFlag=true;
	             	   }
	  				  group.setProPertyList(proPertyDataList);
  			    }
             	if(!otherFlag) {
             		otherPertyDataList.add(item);
             	}
           }
			if(otherPertyDataList.size()>0) {
				DevicePropertyGroupEntity group=new DevicePropertyGroupEntity();
				group.setId(0l);
				group.setGroupCode("OTHER");
				group.setName("其他");
				group.setProPertyList(otherPertyDataList);
				groupDataList.add(group);
			}
		}
		result.put("groupDataList", groupDataList);
		result.put("dataDateVo", dataDateVo);
        return R.ok(result);
    }
    @ApiOperation(value = "设备flux 点位数据", response = VPage.class)
    @ApiImplicitParams({
    	@ApiImplicitParam(name = "start", value = "开始时间毫秒，也支持 -1h -5d 0 是所有时间 ",  paramType = "query", required = false, dataType =  "String"),
    	@ApiImplicitParam(name = "end", value = "结束时间毫秒eg:1738828551",  paramType = "query", required = false, dataType =  "Long"),
    	@ApiImplicitParam(name = "deviceId", value = "",  paramType = "query", required = false, dataType =  "Long"),
    	@ApiImplicitParam(name = "tag", value = "标签",  paramType = "query", required = false, dataType =  "String"),
    	@ApiImplicitParam(name = "tags", value = "多标签",  paramType = "query", required = false, dataType =  "String"),
    	@ApiImplicitParam(name = "statTimeType", value = "周期统计类型: 0 不操作 1 小时 2 天 3 月 4年",  paramType = "query", required = false, dataType =  "Integer"),
//    	@ApiImplicitParam(name = "timeStr", value = "时间",  paramType = "query", required = false, dataType =  "String"),
    	@ApiImplicitParam(name = "curPage", value = "开始页面",  paramType = "query", required = false, dataType =  "Integer"),
    	@ApiImplicitParam(name = "pageSize", value = "每页数量",  paramType = "query", required = false, dataType =  "Integer"),
    })
    @GetMapping("/browsedevicePoint")
    public  R<Map<String, Object>> browsedevicePoint(@RequestParam Map<String, Object> params) {
    	  Map<String, Object> result = new HashMap<>();
    	String tableName =MapUtils.getString("tableName", params);
    	if(tableName==null) {
    		tableName="emsplus";
    	}
    	List<String> tables = Arrays.asList(tableName);
    	Integer curPage =MapUtils.getInteger("curPage", params);
    	Integer pageSize =MapUtils.getInteger("pageSize", params);
    	if(curPage!=null&&pageSize==null) {
    		pageSize=20;
    	}
    	if(curPage==null) {
    		curPage=1;
    		pageSize=20;
    	}
    	String start =MapUtils.getString("start", params);
    	String end =MapUtils.getString("end", params);
    	Long deviceId =MapUtils.getLong("deviceId", params);
    	String tag =MapUtils.getString("tag", params);
    	String tags =MapUtils.getString("tags", params);
    	Integer statTimeType =MapUtils.getInteger("statTimeType", params);
    	if(!params.containsKey("deviceId")) {
   		   return R.error("设备编号 deviceId 不能为空");
   	    }
//    	if(!params.containsKey("tag")&&!params.containsKey("tags")) {
//    		return R.error("设备编号 tag 不能为空");
//    	}
    	 DeviceEntity device=deviceService.getById(deviceId);
         result.put("device", device);
         if(device==null) {
         	return R.error("设备不存在！");
         }
         List<DevicePropertyEntity> proPertyList=null;
         if(device.getDeviceTypeId()!=null&&device.getDeviceTypeId()>0) {
        	    proPertyList=devicePropertyService.getByTypeId(device.getDeviceTypeId(), 1);
             result.put("proPertyList", proPertyList);
         }
         if(device.getIsVirtual()!=null&&device.getIsVirtual()==1) {
         	  return R.ok(result);
         }
         Map<String, String> proPertyKeyMap=null;
         Map<String, String> proPertyCodeKeyMap=null;
     	if(proPertyList!=null&&proPertyList.size()>0) {
     		proPertyKeyMap = proPertyList.stream().collect(Collectors.toMap(DevicePropertyEntity::getDataFormCode, DevicePropertyEntity::getDataCode));
     		proPertyCodeKeyMap = proPertyList.stream().collect(Collectors.toMap(DevicePropertyEntity::getDataCode, DevicePropertyEntity::getDataFormCode));
     	}
     	if(proPertyCodeKeyMap!=null&&proPertyCodeKeyMap.containsKey(tag)) {
     		tag=proPertyCodeKeyMap.get(tag);
     	}
    	String deviceCodeTag=device.getDeviceCode()+"_"+tag;
    	List<String> tagList=new ArrayList<String>();
    	if(tags!=null) {
    		List<String> allTags=StringUtil.splitToList(tags, ",");
        	for(String item:allTags) {
        		if(proPertyCodeKeyMap!=null&&proPertyCodeKeyMap.containsKey(item)) {
        			item=proPertyCodeKeyMap.get(item);
             	}
        		tagList.add(device.getDeviceCode()+"_"+item);
        	}
    	}
    	int timeType=1;
    	if(tagList!=null&&tagList.size()>0) {
    		deviceCodeTag=null;
    	}
    	List<FluxTable> fluxTableList = influxdbService.queryInfluxDataByDeviceCode(bucket, start, end, tables, deviceCodeTag,tagList,curPage,pageSize,false,statTimeType);
    	Map<String,Map<String, Object>> maps = InfluxdbService.queryResultOneRowByTagProcess(fluxTableList,true,timeType);
    	List<DeviceDataDateVo> listData=InfluxdbService.queryResultOneRowToList(maps,timeType);
    	if(tagList!=null&&tagList.size()>0) {
    		deviceCodeTag=tagList.get(0);
    	}
    	long countList =influxdbService.countInfluxDataByDeviceCode(bucket, start, end, tables, deviceCodeTag,false,false,statTimeType);
    	if(proPertyKeyMap!=null) {
    		for(DeviceDataDateVo item:listData) {
        		if(item.getData()!=null) {
        			for (Map.Entry<String,Object> entry : item.getData().entrySet()) {
        				  if(proPertyKeyMap.containsKey(entry.getKey())) {
        					  item.getData().put(proPertyKeyMap.get(entry.getKey()), entry.getValue());
        				  }
        			}
        		}
        	}
    	}
    	VPage<DeviceDataDateVo> page=new VPage<DeviceDataDateVo>(listData, countList, pageSize, curPage);
    	result.put("dataList", page);
    	return R.ok(result);
    }
}